/**
 * Copyright (C) <2023> <Boundivore> <boundivore@foxmail.com>
 * <p>
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the Apache License, Version 2.0
 * as published by the Apache Software Foundation.
 * <p>
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * Apache License, Version 2.0 for more details.
 * <p>
 * You should have received a copy of the Apache License, Version 2.0
 * along with this program; if not, you can obtain a copy at
 * http://www.apache.org/licenses/LICENSE-2.0.
 */
/**
 * 修改配置文件页面
 * @author Tracy
 */
import React, { useEffect, useState, useRef, useCallback } from 'react';
import { useTranslation } from 'react-i18next';
import { useSearchParams } from 'react-router-dom';
import { Tabs, Col, Row, Space, Button, message, App, Typography, Popover, Input, Card, Flex, Tooltip, Checkbox } from 'antd';
import { PlusCircleOutlined, QuestionCircleOutlined } from '@ant-design/icons';
import type { TabsProps, CheckboxProps } from 'antd';
import { Resizable } from 're-resizable';
import _ from 'lodash';
import CryptoJS from 'crypto-js';
import sha256 from 'crypto-js/sha256';
import Base64 from 'crypto-js/enc-base64';
import Utf8 from 'crypto-js/enc-utf8';
import RequestHttp from '@/api';
import APIConfig from '@/api/config';
import useStore from '@/store/store';
import useNavigater from '@/hooks/useNavigater';
import CodeEditor from './components/codeEditor';
import NodeListModal from './components/nodeListModal';
import { ConfigSummaryVo, ConfigGroupVo } from '@/api/interface';
import ContainerCard from '@/components/containerCard';
import { fuzzySearchFiles, getKeyArrayReduce } from '@/utils/helper';
import ThemeToggle from '@/components/themeToggle';
import DownloadConfig from './components/downloadConfig';
import Rollback from './components/rollbackConfig';
import { useConfigState } from './hooks/useConfigState';
import { ConfigStateProvider } from './contexts/configStateContext';
const { Paragraph } = Typography;
const { Search } = Input;

// 从 TabsProps 中提取 items 类型
type TabItem = NonNullable<TabsProps['items']>[number];

// 使用交叉类型将 ConfigSummaryVo 合并到 TabItem 中
type MergedTabItem = TabItem & ConfigSummaryVo;

// 定义扩展后的 TabsProps 类型
type MergedTabsProps = {
	items: MergedTabItem[];
};
const ModifyConfig: React.FC = () => {
	const { t } = useTranslation();
	const [searchParams] = useSearchParams();
	const id = searchParams.get('id');
	const serviceName = searchParams.get('name') || '';
	const [tabsData, setTabsData] = useState<MergedTabsProps['items']>([]);
	const [allTabsData, setAllTabsData] = useState<MergedTabsProps['items']>([]);
	const [activeTab, setActiveTab] = useState<string>('');
	const [activeContent, setActiveContent] = useState<ConfigGroupVo[]>([]);
	const [codeEdit, setCodeEdit] = useState<string>('');
	const [codeVersion, setCodeVersion] = useState<string>('');
	const [currentGroupIndex, setCurrentGroupIndex] = useState(0);
	const [isModalOpen, setIsModalOpen] = useState<boolean>(false);
	const [configPath, setConfigPath] = useState<string>('');
	const [files, setFiles] = useState<string[]>([]);
	const { setIsConfigModified, isConfigModified } = useStore();
	const { configGroupInfo, setConfigGroupInfo } = useConfigState();
	const [messageApi, contextHolder] = message.useMessage();
	const { navigateToService } = useNavigater();
	const { modal } = App.useApp();

	const [checkedList, setCheckedList] = useState<string[]>([]);

	const editorRef = useRef<{ handleSave: () => string } | null>(null);
	// const textRef = useRef<(HTMLSpanElement | null)[]>([]);

	const [isDarkMode, setIsDarkMode] = useState(() => {
		return localStorage.getItem('theme') === 'dark';
	});
	const [pathList, setPathList] = useState<string[]>([]);
	const [configData, setConfigData] = useState([]); // 存储原始数据

	// 获取初始数据
	const getConfigFile = async () => {
		const api = APIConfig.listSummary;
		const params = { ClusterId: id, ServiceName: serviceName };
		const data = await RequestHttp.get(api, { params });
		const { ConfigSummaryList } = data.Data;
		setConfigData(ConfigSummaryList); // 保存原始数据
	};
	//获取具体文件内容
	const getFileContent = async () => {
		// setLoading(true);
		const api = APIConfig.listByGroup;
		const { ConfigPath, Filename } = tabsData?.find(item => item.key === activeTab) ?? { ConfigPath: '' };
		const params = { ClusterId: id, ServiceName: serviceName, Filename, ConfigPath };
		const data = await RequestHttp.get(api, { params });
		const {
			Data: { ConfigGroupList }
		} = data;
		// setLoading(false);
		// paramData = ConfigGroupList;
		const copyData = _.cloneDeep(ConfigGroupList);
		const codeData = Utf8.stringify(Base64.parse(copyData[0].ConfigData));
		setActiveContent(copyData);
		setCodeEdit(codeData);
		setCodeVersion(copyData[0].ConfigNodeList[0].ConfigVersion);
		setConfigGroupInfo(copyData);
		setConfigPath(ConfigPath);
	};

	// 生成tabs数据的effect
	useEffect(() => {
		if (!configData.length) return;
		let fileNames: string[] = [];
		const tabs = configData.map((item: ConfigSummaryVo) => {
			fileNames.push(item.Filename);
			return {
				...item,
				key: item.ConfigPath,
				label: (
					<Popover
						placement="left"
						content={
							<Paragraph className="mb-0" copyable>
								{item.ConfigPath}
							</Paragraph>
						}
					>
						<Checkbox value={item.ConfigPath} onChange={onCheckChange} checked={checkedList.includes(item.ConfigPath)}>
							{item.Filename}
						</Checkbox>
					</Popover>
				)
			};
		});
		setFiles(fileNames);
		setTabsData(tabs);
		setAllTabsData(tabs);
		setActiveTab(tabs[0].key); // 默认选中第一项
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [configData, checkedList]); // 依赖configData和checkedList
	const onCheckChange: CheckboxProps['onChange'] = e => {
		console.log(`checked = ${e.target.checked}`);
		const { checked, value } = e.target;
		let list: string[] = [];
		const removeByFilter = (arr, target) => arr.filter(item => item !== target);
		if (checked) {
			// 创建新数组,不要修改原数组
			list = [...checkedList, value];
		} else {
			// 过滤创建新数组

			list = removeByFilter(checkedList, value);
			// return checkedList.filter(item => item !== value);
		}

		setCheckedList(list);
	};

	useEffect(() => {
		setActiveContent(configGroupInfo);
	}, [configGroupInfo]);
	useEffect(() => {
		getConfigFile();
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, []);
	useEffect(() => {
		activeTab && getFileContent();
		// eslint-disable-next-line react-hooks/exhaustive-deps
	}, [activeTab]);
	const handleClick = (index: number) => {
		if (isConfigModified) {
			processEditorData();
			setConfigGroupInfo(configGroupInfo);
		}

		setCurrentGroupIndex(index);
		setCodeEdit(Utf8.stringify(Base64.parse(activeContent[index].ConfigData)));
		setCodeVersion(activeContent[index].ConfigNodeList[0].ConfigVersion);
		setIsModalOpen(true);
	};
	const handleModalOk = useCallback((targetGroupIndex: number, data: ConfigGroupVo[]) => {
		// 新建分组，添加到其他分组
		setIsModalOpen(false);
		if (targetGroupIndex >= data.length) {
			setCurrentGroupIndex(data.length - 1);
		} else {
			setCurrentGroupIndex(targetGroupIndex);
		}
	}, []);
	const handleModalCancel = useCallback(() => {
		setIsModalOpen(false);
	}, []);
	const processEditorData = () => {
		const editorValue = editorRef.current?.handleSave() ?? '';
		const base64Data = btoa(unescape(encodeURIComponent(editorValue)));
		const hashDigest = sha256(editorValue).toString(CryptoJS.enc.Hex);

		_.merge(configGroupInfo[currentGroupIndex], {
			Sha256: hashDigest,
			ConfigData: base64Data
		});
	};
	const saveChange = async () => {
		const api = APIConfig.saveByGroup;
		processEditorData();
		const params = {
			ClusterId: id,
			ConfigGroupList: configGroupInfo,
			ServiceName: serviceName
		};
		const data = await RequestHttp.post(api, params);
		const { Code } = data;
		if (Code === '00000') {
			messageApi.success(t('messageSuccess'));
			setIsConfigModified(false);
			// navigateToService();
		}
	};

	const [width, setWidth] = useState(300);

	const handleSearch = (text: string) => {
		const result = fuzzySearchFiles(files, text);
		const filteredTabsData = allTabsData.filter(file => result.includes(file.Filename));
		setTabsData(filteredTabsData);
	};

	const checkAll = pathList.length === checkedList.length;
	const indeterminate = checkedList.length > 0 && checkedList.length < pathList.length;
	useEffect(() => {
		const paths = getKeyArrayReduce(tabsData, 'key');
		setPathList(paths);
	}, [tabsData]);

	const onCheckAllChange: CheckboxProps['onChange'] = e => {
		setCheckedList(e.target.checked ? pathList : []);
	};

	return (
		<ConfigStateProvider>
			<ContainerCard>
				{contextHolder}
				<Flex gap="middle" className="w-[100%] overflow-hidden">
					<Resizable
						size={{ width, height: 'auto' }}
						onResizeStop={(_e, _direction, _ref, d) => {
							setWidth(width + d.width); // 更新宽度
						}}
						enable={{
							right: true // 只允许从右侧拖动
						}}
						minWidth={200}
						maxWidth={450}
					>
						<Card
							title={
								<div className="flex items-center">
									<img src={`/service_logo/${serviceName.toLowerCase()}.svg`} width="16" height="16" />
									<span className="pl-[5px]">{serviceName}</span>
								</div>
							}
							className="w-[100%]"
							extra={<DownloadConfig fileList={checkedList.join(',')} />}
						>
							<Search
								placeholder={t('inputFileName')}
								allowClear
								className="mb-[20px] w-[100%]"
								onSearch={value => handleSearch(value)}
							/>
							<Checkbox indeterminate={indeterminate} onChange={onCheckAllChange} checked={checkAll}>
								全选
							</Checkbox>
							<Tabs
								className="h-[550px]"
								tabBarStyle={{ width: '100%' }}
								tabPosition="left"
								items={tabsData}
								activeKey={activeTab}
								onChange={activeKey => {
									if (isConfigModified) {
										modal.confirm({
											title: t('warning'),
											content: t('warningText'),
											okText: t('confirm'),
											cancelText: t('cancel'),
											onOk: async () => {
												setActiveTab(activeKey);
												setIsConfigModified(false);
												setCurrentGroupIndex(0);
											}
										});
									} else {
										setActiveTab(activeKey);
										setCurrentGroupIndex(0);
									}
								}}
							/>
						</Card>
					</Resizable>
					<Row className="w-[100%] h-[100%] min-w-[1px]">
						<Col span={4}>
							<Card
								title={
									<Space>
										{t('setGroup')}
										<Tooltip title={t('groupPrompt')}>
											<QuestionCircleOutlined />
										</Tooltip>
									</Space>
								}
								bordered={true}
								className="h-[100%] overflow-y-auto max-h-[690px] min-w-[130px]"
							>
								<Space direction="vertical">
									{configGroupInfo.map((_group, index) => {
										return (
											<Space key={index}>
												<Button
													key={index}
													size="middle"
													type={index === currentGroupIndex ? 'primary' : 'default'}
													onClick={() => {
														if (isConfigModified) {
															processEditorData();
															setConfigGroupInfo(configGroupInfo);
														}

														setCurrentGroupIndex(index);
														setCodeEdit(Utf8.stringify(Base64.parse(activeContent[index].ConfigData)));
														setCodeVersion(activeContent[index].ConfigNodeList[0].ConfigVersion);
													}}
												>
													{t('group', { name: index + 1 })}
												</Button>
												<PlusCircleOutlined style={{ fontSize: '16px' }} onClick={() => handleClick(index)} />
											</Space>
										);
									})}
								</Space>
							</Card>
						</Col>
						<Col className="min-h-[500px]" span={20}>
							<Card
								title={
									<Flex vertical={true}>
										<Space className="pt-[15px] pb-[10px]">
											<Paragraph className="mb-0 text-[16px]" copyable>
												{configPath}
											</Paragraph>
											<span>
												{t('version')}
												{codeVersion}
											</span>
										</Space>
										<Flex justify="space-between">
											<Space className="pb-[10px]">
												<Button type="primary" onClick={saveChange}>
													{t('save')}
												</Button>
												<DownloadConfig fileList={configPath} />
												<Rollback
													fileName={activeTab.substring(activeTab.lastIndexOf('/') + 1)}
													configPath={configPath}
													oldCode={codeEdit}
												/>
												<Button onClick={navigateToService}>{t('back')}</Button>
											</Space>
											<ThemeToggle onChange={setIsDarkMode} />
										</Flex>
									</Flex>
								}
							>
								<CodeEditor ref={editorRef} data={codeEdit} index={currentGroupIndex} darkMode={isDarkMode} />
							</Card>
						</Col>
					</Row>
				</Flex>

				{isModalOpen ? (
					<NodeListModal
						isModalOpen={isModalOpen}
						groupIndex={currentGroupIndex}
						handleOk={handleModalOk}
						handleCancel={handleModalCancel}
					/>
				) : null}
			</ContainerCard>
		</ConfigStateProvider>
	);
};

export default ModifyConfig;
